#include "Camera.h"



Camera::Camera():mPos(0.0f, 0.0f, 0.5f),mViewCenter(0.0f, 0.0f, 0.0f),mUp(0.0f, 1.0f, 0.0f)
{
	mRightMove = false;
	mLeftMove = false;
	mBackMove = false;
	mForwardMove = false;
}


Camera::~Camera()
{
}

glm::mat4 Camera::Update(float deltaTime, glm::mat4& view)
{

	float moveSpeed = 1.0f;
	deltaTime = deltaTime / 1000000000.0;
	Vector3f forwardDirection = mViewCenter - mPos;
	forwardDirection.Normalize();
	Vector3f rightDirection = Cross(forwardDirection, mUp);
	rightDirection.Normalize();
	if (mLeftMove) {
		Vector3f delta = rightDirection*deltaTime*moveSpeed;
		mPos = mPos - delta;
		mViewCenter = mViewCenter - delta;
	}
	if (mRightMove) {
		Vector3f delta = rightDirection*deltaTime*moveSpeed;
		mPos = mPos + delta;
		mViewCenter = mViewCenter + delta;
	}
	if (mForwardMove) {
		Vector3f delta = forwardDirection*deltaTime*moveSpeed;
		mPos = mPos + delta;
		mViewCenter = mViewCenter + delta;
	}
	if (mBackMove) {
		Vector3f delta = forwardDirection*deltaTime*moveSpeed;
		mPos = mPos - delta;
		mViewCenter = mViewCenter - delta;
	}
	view =glm::lookAt(glm::vec3(mPos.x, mPos.y, mPos.z), glm::vec3(mViewCenter.x, mViewCenter.y, mViewCenter.z), glm::vec3(mUp.x, mUp.y, mUp.z));
	return view;
}

void Camera::OnKeyUp(char code)
{
	switch (code)
	{
	case  'A':
		mLeftMove = false;
		break;
	case  'D':
		mRightMove = false;
		break;
	case  'W':
		mForwardMove = false;
		break;
	case  'S':
		mBackMove = false;
		break;
	case  'a':
		mLeftMove = false;
		break;
	case  'd':
		mRightMove = false;
		break;
	case  'w':
		mForwardMove = false;
		break;
	case  's':
		mBackMove = false;
		break;
	default:
		break;
	}
}

void Camera::OnKeyDown(char code)
{
	switch (code)
	{
	case  'A':
		mLeftMove = true;
		break;
	case  'D':
		mRightMove = true;
		break;
	case  'W':
		mForwardMove = true;
		break;
	case  'S':
		mBackMove = true;
		break;
	case  'a':
		mLeftMove = true;
		break;
	case  'd':
		mRightMove = true;
		break;
	case  'w':
		mForwardMove = true;
		break;
	case  's':
		mBackMove = true;
		break;
	default:
		break;
	}
}

void Camera::OnRMouseDown()
{
}

void Camera::OnRMouseUp()
{
}

void Camera::OnMouseMove(double x,double y)
{
	float angleRotatedByRight = y / 1000.0f;
	float angleRotatedByUp = x / 1000.0f;
    Yaw(-angleRotatedByUp);
	Pitch(-angleRotatedByRight);
}

void Camera::SwitchTo3D()
{
}

void Camera::SwitchTo2D()
{
}

void Camera::SetPosition(float x, float y, float z)
{
	mPos =Vector3f(x,y,z);
}

void Camera::Pitch(float angle)
{
	Vector3f viewDirection = mViewCenter - mPos;
	viewDirection.Normalize();
	Vector3f rightDirection = Cross(viewDirection, mUp);
	rightDirection.Normalize();
	RotateView(angle, rightDirection.x, rightDirection.y, rightDirection.z);
}

void Camera::Yaw(float angle)
{
	RotateView(angle, mUp.x, mUp.y, mUp.z);
}

void Camera::RotateView(float angle, float x, float y, float z)
{
	Vector3f viewDirection = mViewCenter - mPos;
	Vector3f newDirection(0.0f, 0.0f, 0.0f);
	float C = cosf(angle);
	float S = sinf(angle);
	Vector3f tempX(C + x*x*(1 - C), x*y*(1 - C) - z*S, x*z*(1 - C) + y*S);
	newDirection.x = tempX*viewDirection;
	Vector3f tempY(x*y*(1 - C) + z*S, C + y*y*(1 - C), y*z*(1 - C) - x*S);
	newDirection.y = tempY*viewDirection;
	Vector3f tempZ(x*z*(1 - C) - y*S, y*z*(1 - C) + x*S, C + z*z*(1 - C));
	newDirection.z = tempZ*viewDirection;
	mViewCenter = mPos + newDirection;
}
